package com.css.zfzx.fxpg.common.utils.cluster;

import com.css.zfzx.fxpg.modules.buildings.data.viewobjects.FxBuildingsQueryParams;
import com.google.common.collect.ImmutableMap;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MarkerClusterer {

    private Map<Integer, Float> zoom2value = ImmutableMap.<Integer, Float>builder()
            .put(1, 60.0f).put(2, 30.0f).put(3, 8.0f).put(4, 8.0f).put(5, 0.7f).put(6, 0.6f)
            .put(7, 0.5f).put(8, 0.4f).put(9, 0.2f).put(10, 0.1f).put(11, 0.045f).put(12, 0.03f)
            .put(13, 0.02f).put(14, 0.009f).put(15, 0.0088f).put(16, 0.005f).put(17, 0.0015f).put(18, 0.0f)
            .build();

    public static void main(String[] args) {
        int zoom = 11;
        FxBuildingsQueryParams queryParams = new FxBuildingsQueryParams();
        queryParams.setBounds("109.39746 33.87406,125.96485 40.85039");//109.39746 33.87406,125.96485 40.85039 | 71.19141 21.25661,137.46094 49.35948
        queryParams.setZoom(zoom);
        //queryParams.setProvince("山东省");//山东省 北京市

        /*ClusterTest cTest = new ClusterTest();
        List<QhProbabilityEarthquakeDangerEntity> result = cTest.sqlBatchSelectEntities(queryParams);

        System.out.println(zoom + "--" + result.size());
        QhProbabilityEarthquakeDangerEntity entity = result.get(0);
        System.out.println("uuid: " + result.get(0).getUuid() + ": A: " + entity.getA() + ", B: " + entity.getB());*/


        /*
        List<Marker> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Point position = new Point(i + 1.0, i + 2.0);
            Marker marker = new Marker(position);
            list.add(marker);
        }
        Point p = new Point(3.0, 4.0);
        Marker m = new Marker(p);
        System.out.println(list.indexOf(m));*/
    }

    private List<Marker> markers ;
    public List<Cluster> clusters;
    public float gridSize;
    public int maxZoom;
    public int minClusterSize;
    public boolean isAverageCenter;

    /**
     * MarkerClusterer
     * @class 用来解决加载大量点要素到地图上产生覆盖现象的问题，并提高性能
     * @constructor
     * @param
     *    markers {Array<Marker>} 要聚合的标记数组<br />
     *    girdSize {Number} 聚合计算时网格的像素大小，默认60<br />
     *    maxZoom {Number} 最大的聚合级别，大于该级别就不进行相应的聚合<br />
     *    minClusterSize {Number} 最小的聚合数量，小于该数量的不能成为一个聚合，默认为2<br />
     *    isAverangeCenter {Boolean} 聚合点的落脚位置是否是所有聚合在内点的平均值，默认为否，落脚在聚合内的第一个点<br />
     */
    public MarkerClusterer (List<Marker> markers, Bounds bounds, int zoom) {
        this.markers = markers;
        this.clusters = new ArrayList<>();
        this.gridSize = zoom2value.get(zoom);
        this.maxZoom = zoom;
        this.minClusterSize = 2;
        this.isAverageCenter = false;

        this.createClusters(bounds, zoom);
    }

    private void createClusters(Bounds mapBounds, int zoom) {
        Bounds extendedBounds = mapBounds.getExtendedBounds(this.gridSize, zoom);
        for(int i = 0, size = this.markers.size(); i < size; i++){
            Marker marker = this.markers.get(i);
            if(!marker.isInCluster && extendedBounds.containsPoint(marker.position)) {
                this.addToClosestCluster(marker, zoom);
            }
        }
    };

    private void addToClosestCluster(Marker marker, int zoom){
        double distance = Double.POSITIVE_INFINITY, d = 0;
        Cluster clusterToAddTo = null;
        Cluster cluster = null;
        Point center = null;
        for(int i = 0, size = this.clusters.size(); i < size; i++) {
            cluster = this.clusters.get(i);
            center = cluster.center;
            if(center != null){
                d = center.getDistance(marker.position);
                if(d < distance){
                    distance = d;
                    clusterToAddTo = cluster;
                }
            }
        }

        if (clusterToAddTo != null && clusterToAddTo.isMarkerInClusterBounds(marker)){
            clusterToAddTo.addMarker(marker, zoom);
        } else {
            cluster = new Cluster(this);
            cluster.id = marker.id;
            cluster.name = marker.name;
            cluster.addMarker(marker, zoom);
            this.clusters.add(cluster);
        }
    }



}










